#include <LittleFS.h>
#include <WebServer.h>

#define WEB_DEBUG false
#define MAX_LINE_LENGTH 256
#define QueueElementSize 30

#ifndef WEBSERVER_PORT
#define WEBSERVER_PORT 80
#endif


WebServer server(WEBSERVER_PORT);
char text_msg_str[32] = "";
char reply_msg_str[MAX_LINE_LENGTH] = "Umeko Online!";
char web_remote_IP[15]="";



void init_web(const char *now_IP=NULL){

    if (!LittleFS.begin()) {
        Serial.println("LittleFS initialization failed!");
        return;
    }
    server.on("/", HTTP_GET, [](){
        String htmlContent;
        File file = LittleFS.open("/terminal.html", "r");
        if (file) {
        while (file.available()) {
            htmlContent += (char)file.read();
        }
        file.close();
        server.send(200, "text/html", htmlContent);
        } else {
        server.send(404, "text/plain", "File not found");
        }
    });
    server.on("/terminal", HTTP_POST, [](){
        // 读取文本数据
        String textData = server.arg("plain");
        // 在串口中打印接收到的文本数据
        strcpy(web_remote_IP, server.client().remoteIP().toString().c_str());
        Serial.print("Received from:");
        Serial.print(web_remote_IP);
        Serial.println(": " + textData);
        if(WEB_DEBUG){
            String debug_message = "Headers: \n";
            for (uint8_t i = 0; i < server.headers(); i++) {
                debug_message += " " + server.headerName(i) + ": " + server.header(i) + "\n";
            }
            debug_message += "Args: \n";
            for (uint8_t i = 0; i < server.args(); i++) {
                debug_message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
            }
        Serial.println(debug_message);
        }
        if (strlen((const char*)textData.c_str()) != 0){
            strcpy(text_msg_str, textData.c_str());
        }
        server.send(200, "text/plain", "Received successfully");
    });
    
    server.on("/update", HTTP_POST, [](){
        if (strlen((const char*)reply_msg_str) != 0){
            server.send(200, "text/plain", reply_msg_str);
            strcpy(reply_msg_str, "");
        }else{
            server.send(404, "text/plain", "Empty Output");
        } 
    });


    if(now_IP == NULL){now_IP = WiFi.localIP().toString().c_str();}
    Serial.printf("WEB Server started at %s:%d\n", now_IP, WEBSERVER_PORT);
    server.begin();
    
}

void server_task(const char *now_IP=NULL){
    init_web(now_IP);
    for(;;){
        server.handleClient();
        vTaskDelay(10);
    }
}
// 检查是否有连接需要处理，非阻塞式
void server_handleClient(){
    server.handleClient();
}

typedef struct{
  char line[MAX_LINE_LENGTH];
} message_t;

class QuePrinter: public Print{
    public:
        QuePrinter();
        size_t write(uint8_t) override;
        size_t write(const uint8_t *buffer, size_t size) override;
        char* get();
        size_t update();
        QueueHandle_t QueueHandle;
    private: 
        // char msgBuffer[MAX_LINE_LENGTH];
        message_t *msgBuffer = (message_t *)malloc(sizeof(message_t));
};

QuePrinter::QuePrinter(){
    this->QueueHandle = xQueueCreate(QueueElementSize, sizeof(message_t));
    if(QueueHandle == NULL){
        Serial.println("Queue could not be created.");
        while(1) delay(1000); // Halt at this point as is not possible to continue
    }
}


size_t QuePrinter::write(uint8_t data){
    message_t *msg = (message_t *)malloc(sizeof(message_t));
    if (msg == NULL) {
      return 0; 
    }
    msg->line[0] = (char)data;
    if (xQueueSend(this->QueueHandle, (void*)&msg, 0) == pdPASS) {
        return 1;
    }else{
        free(msg);
        return 0;
    }
}

size_t QuePrinter::write(const uint8_t *buffer, size_t size){
    size_t n = 0;
    message_t *msg = (message_t *)malloc(sizeof(message_t));
    if (msg == NULL) {
      return 0; 
    }
    while(size--) {
        if (n < MAX_LINE_LENGTH) {msg->line[n] = (char)buffer[n]; n++;}
        else {break;}
    }
    msg->line[n] = (char)buffer[n];  // 结束符别忘了
    if (xQueueSend(this->QueueHandle, (void*)msg, 0) == pdPASS) {
        // Serial.printf("%s PUSHED INTO QUE %d\n", msg->line, n);
        return n;
    }else{
        // Serial.printf("%s NOT INTO QUE\n", msg->line, msg->line, n);
        free(msg);
        return 0;
    }
}

char* QuePrinter :: get(){
    message_t message;
    if (xQueueReceive(this->QueueHandle, &message, portMAX_DELAY) == pdPASS) {
        strncpy(this->msgBuffer->line, message.line, MAX_LINE_LENGTH);
        return this->msgBuffer->line;
    } else {
        return NULL;
    }
}

// 将从本机的数据输出队列数据更新到用户端中。
size_t QuePrinter :: update(){
    // Serial.println(strlen((const char*)reply_msg_str));
    if (strlen((const char*)reply_msg_str) == 0){
        message_t message;
        if (xQueueReceive(this->QueueHandle, &message, 0) == pdPASS) {
            strncpy(reply_msg_str, message.line, MAX_LINE_LENGTH);
            // Serial.println(message.line);
            return 1; 
        } else {return 0;}
    } else {return 0;}
}